/**
	Returns the FFVideoFormat identifier based on the given parameters. If the parameters don't match a defined identifier according to FCPXML v1.5, the method will return the string "FFVideoFormatRateformatUndefined".
	
	- parameter fromWidth: The width of the frame as an integer.
	- parameter height: The height of the frame as an integer.
	- parameter frameRate: The frame rate as a float.
	- parameter isInterlaced: A boolean value indicating if the format is interlaced.
	- parameter is16x9: A boolean value indicating if the format has an aspect ratio of 16:9.
	
	- returns: A string of the FFVideoFormat identifier.
	*/

// vlevin @ 2022-11-05 FCP允许的格式，参考
// vlevin @ 2022-11-05 https://developer.apple.com/documentation/professional_video_applications/fcpxml_reference/format/predefined_video_formats?language=objc

const stdFrameRates = [23.98, 24, 25, 29.97, 30, 50, 59.94, 60]
export const formatUndefined = 'FFVideoFormatRateUndefined'
export const formatAudio = 'FFVideoFormat1080p60'

export function getFFVideoFormat(mediaInfo) {
  const { width, height, frameRate, fieldOrder, isRotated } = mediaInfo
  const isInterlaced = fieldOrder !== 'progressive'
  const is16x9 = Boolean(width / height === 16 / 9)

  let ffVideoFormat = 'FFVideoFormat'
  ffVideoFormat = isRotated
    ? defineWidthHeight(height, width, ffVideoFormat)
    : defineWidthHeight(width, height, ffVideoFormat)

  if (isInterlaced === false) {
    ffVideoFormat += 'p'
  } else {
    if (frameRate === 59.94 || frameRate == 50) {
      ffVideoFormat += 'i'
    } else {
      return formatUndefined
    }
  }

  ffVideoFormat = defineFrameRate(frameRate, ffVideoFormat)

  if (is16x9 == true && width == 720) {
    if (height == 486 || height == 576 || height == 480) {
      ffVideoFormat += '_16x9'
    }
  }

  return ffVideoFormat
}

function defineWidthHeight(width, height, ffVideoFormat) {
  switch (width) {
    case 1920:
      if (height === 1080) {
        ffVideoFormat += '1080'
        return ffVideoFormat
      } else {
        return formatUndefined
      }
    case 1280:
      switch (height) {
        case 1080:
          ffVideoFormat += '1280x1080'
          return ffVideoFormat
        case 720:
          ffVideoFormat += '720'
          return ffVideoFormat
        default:
          return formatUndefined
      }
    case 1440:
      if (height === 1080) {
        ffVideoFormat += '1440x1080'
        return ffVideoFormat
      } else {
        return formatUndefined
      }
    case 2048:
      switch (height) {
        case 1080:
          ffVideoFormat += '2048x1080'
          return ffVideoFormat
        case 1024:
          ffVideoFormat += '2048x1024'
          return ffVideoFormat
        case 1152:
          ffVideoFormat += '2048x1152'
          return ffVideoFormat
        case 1536:
          ffVideoFormat += '2048x1536'
          return ffVideoFormat
        case 1556:
          ffVideoFormat += '2048x1556'
          return ffVideoFormat
        default:
          return formatUndefined
      }
    case 3840:
      if (height == 2160) {
        ffVideoFormat += '3840x2160'
        return ffVideoFormat
      } else {
        return formatUndefined
      }
    case 4096:
      switch (height) {
        case 2048:
          ffVideoFormat += '4096x2048'
          return ffVideoFormat
        case 2160:
          ffVideoFormat += '4096x2160'
          return ffVideoFormat
        case 2304:
          ffVideoFormat += '4096x2304'
          return ffVideoFormat
        case 3112:
          ffVideoFormat += '4096x3112'
          return ffVideoFormat
        default:
          return formatUndefined
      }
    case 5120:
      switch (height) {
        case 2160:
          ffVideoFormat += '5120x2160'
          return ffVideoFormat
        case 2560:
          ffVideoFormat += '5120x2560'
          return ffVideoFormat
        case 2700:
          ffVideoFormat += '5120x2700'
          return ffVideoFormat
        default:
          return formatUndefined
      }
    case 640:
      switch (height) {
        case 360:
          ffVideoFormat += '640x360'
          return ffVideoFormat
        case 480:
          ffVideoFormat += '640x480'
          return ffVideoFormat
        default:
          return formatUndefined
      }
    case 720:
      switch (height) {
        case 480:
          ffVideoFormat += 'DV720x480'
          return ffVideoFormat
        case 486:
          ffVideoFormat += '720x486'
          return ffVideoFormat
        case 576:
          ffVideoFormat += '720x576'
          return ffVideoFormat
        default:
          return formatUndefined
      }
    case 960:
      switch (height) {
        case 540:
          ffVideoFormat += '960x540'
          return ffVideoFormat
        case 720:
          ffVideoFormat += '960x720'
          return ffVideoFormat
        default:
          return formatUndefined
      }
    default:
      return formatUndefined
  }
}

function defineFrameRate(frameRate, ffVideoFormat) {
  switch (frameRate) {
    case 23.98:
      ffVideoFormat += '2398'
      return ffVideoFormat
    case 24:
      ffVideoFormat += '24'
      return ffVideoFormat
    case 25:
      ffVideoFormat += '25'
      return ffVideoFormat
    case 29.97:
      ffVideoFormat += '2997'
      return ffVideoFormat
    case 30:
      ffVideoFormat += '30'
      return ffVideoFormat
    case 50:
      ffVideoFormat += '50'
      return ffVideoFormat
    case 59.94:
      ffVideoFormat += '5994'
      return ffVideoFormat
    case 60:
      ffVideoFormat += '60'
      return ffVideoFormat
    default:
      return formatUndefined
  }
}

// vlevin @ 2022-11-05 将视频的帧率换算成一个最靠近的标准帧率
// vlevin @ 2022-11-05 标准帧率即FCP format允许的值之一
export function getStdFrameRate(frameRate) {
  if (stdFrameRates.includes(frameRate)) {
    return frameRate
  } else {
    const map = new Map()
    for (const stdFrameRate of stdFrameRates) {
      map.set(Math.abs(frameRate - stdFrameRate), stdFrameRate)
    }
    const targetKey = Math.min(...Array.from(map.keys()))
    return map.get(targetKey)
  }
}

// vlevin @ 2022-11-05 计算倍数。因为fcpxml不允许小数，如果frameRate为小数，则将其不断x10直到变为整数
export function getMultiple(float) {
  let multiple = 1
  while (parseInt(float * multiple) !== parseFloat(float * multiple)) {
    multiple *= 10
  }
  return multiple
}
